package com.wl.dao;

import com.wl.entity.Person;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;

import java.util.List;

/*
 * 1.Repository是一个空接口，即是一个标记接口
 * 2.若我们定义的接口继承了Repository，则该接口会被IOC容器识别为一个Repository Bean
 * 注入到IOC容器中，进而可以在该接口中定义满足一定规则的接口
 * 3.实际上也可以通过一个注解@RepositoryDefination 注解来替代Repository接口
 */
//@RepositoryDefinition(domainClass=Person.class,idClass=Integer.class)
public interface PersonDAO extends Repository<Person, Integer> {

    /**
     * 简单的条件查询的方法定义规范
     *         方法定义规范如下：
     * 简单条件查询：查询某一个实体或者集合
     * 按照SpringData规范，查询方法于find|read|get开头，涉及条件查询时，条件的属性用条件关键字连接，要注意的是：属性首字母需要大写。
     * 支持属性的级联查询；若当前类有符合条件的属性， 则优先使用， 而不使用级联属性。 若需要使用级联属性， 则属性之间使用 _ 进行连接。
     */

    // 通过id查找实体
    Person getById(Integer id);

    Person findByIdAndName(Integer id, String name);

    List<Person> findByEmailLike(String email);

    // 级联查询，查询address的id等于条件值
    List<Person> findByAddressId(Integer addressId);

    // 自定义的查询,直接写jpql语句; 查询id<? 或者 名字 like?的person集合
    @Query("from Person where id < ?1 or name like ?2")
    List<Person> testPerson(Integer id, String name);

    // 自定义的查询,直接写jpql语句; 查询id<? 或者 名字 like?的person集合
    @Query("from Person where id < :id or name like %:name%")
    List<Person> testPerson2(@Param("id")Integer id, @Param("name")String name);

    // 自定义查询之子查询,直接写jpql语句; 查询出id最大的person
    @Query("from Person where id = (select max(p.id) from Person as p)")
    Person testSubquery();

    // 指定本地sql
    @Query(value="select * from jpa_persons where id = :id", nativeQuery = true)
    Person getPersonByIdWithSQL(@Param("id") Integer id);

    //可以通过自定义的 JPQL 完成 UPDATE 和 DELETE 操作. 注意: JPQL 不支持使用 INSERT
    //在 @Query 注解中编写 JPQL 语句, 但必须使用 @Modifying 进行修饰. 以通知 SpringData, 这是一个 UPDATE 或 DELETE 操作
    //UPDATE 或 DELETE 操作需要使用事务, 此时需要定义 Service 层. 在 Service 层的方法上添加事务操作.
    //默认情况下, SpringData 的每个方法上有事务, 但都是一个只读事务. 他们不能完成修改操作!
    @Modifying
    @Query("UPDATE Person p SET p.name = :name WHERE p.id < :id")
    int updatePersonById(@Param("id")Integer id, @Param("name")String updateName);
}
